package Game.GameElements
{
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2FixtureDef;
	import flash.filters.ColorMatrixFilter;
	import flash.text.TextField;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
	import Game.GameCamera;
	import Game.Online.Messages.Message;
	import Game.Online.Messages.MessageDoRocket;
	import Game.Online.Messages.MessageCorrectPosition;
	import Game.Online.Messages.MessagesHandler;
	import Game.Online.OnlineManager;

	import flash.display.DisplayObject;
	import flash.events.TimerEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;

	import Common.Utils;
	import Common.Managers.SwfManager;
	
	import Game.AI.EnemyTankAI;
	import Game.Effects.Explosion;
	import Game.GameStates.GameState;
	import Game.World;
	/**
	 * ...
	 * @author 
	 */
	public class Tank extends GameObject
	{
		public static const DIRECTION_UP:int 		= 0;
		public static const DIRECTION_RIGHT:int 	= 1;
		public static const DIRECTION_DOWN:int 		= 2;
		public static const DIRECTION_LEFT:int 		= 3;		
		
		public static const TYPE_GAME_PLAYER:int 	= 0;
		public static const TYPE_REMOTE_PLAYER:int 	= 1;
		public static const TYPE_AI_BOT:int 		= 2;
		
		public static var m_swfPath:String 			= Settings.pathRes + "swf/tanks.swf";
		private static var m_tankType:Array 		= ["tank1", "tank2", "tank3", "tank4"];
		private var m_currentDirection:int 			= DIRECTION_UP;
		private var m_currentSpeed:int				= 5;
		public var m_typeGamePlayer:int 			= TYPE_AI_BOT;
		public var m_enemyAI:EnemyTankAI 			= null;		
		private var m_isAnimationStoped:Boolean 	= false;		
		
		public static var m_gamePlayer:GameObject	= null;
		
		private var m_timerBlinking:Timer			= null;
		
		public var m_lastTimeRocket:uint 			= getTimer();
		
		private var m_healthBar:Sprite				= null;
		private var m_health:int					= 100;
		private var m_stamina:int					= 12;
		private var m_playerName:String				= "BOT";
		
		public var m_remoteId:String				= "";
		
		public var m_networkUpdate:uint					= getTimer();
		
		public function Tank(posX:int = 0, posY:int = 0, startRot:int = 0, type:int = 1, typeGamePlayer:int = TYPE_AI_BOT, enemyDifficulty:int = EnemyTankAI.EASY) 
		{
			// Add to main sprite
			super(posX, posY, startRot, m_swfPath, m_tankType, type, true, false);
			World.instance.objectLayer.addChild(this);
			m_healthBar = SwfManager.instance.getSprite(m_swfPath, "HealthBar") as Sprite;
			
			m_typeGamePlayer = typeGamePlayer;
			if (m_typeGamePlayer == TYPE_GAME_PLAYER)
			{
				for each(var player:GameObject in gameObjects)
				{
					if (player is Tank && (player as Tank).isGamePlayer())
					{
						throw("Double game player");
					}
				}
				m_gamePlayer = this;
				
				GameCamera.instance.goTo(posX, posY);
				
				(m_healthBar.getChildByName("Name") as TextField).text = m_playerName;
			}
			else if (m_typeGamePlayer == TYPE_AI_BOT)
			{	// Create AI
				m_enemyAI = new EnemyTankAI(this, enemyDifficulty);
				
				isEnemy = true;
			}
			
			if (gameObjects != null)
			{
				gameObjects.push(this);
			}
		}
		
		public static function deserialize(data:ByteArray):Tank
		{
			var startX:int = data.readInt();
			var startY:int = data.readInt();
			var startRot:int = data.readInt();
			var type:int = data.readInt();
			var difficulty:int = data.readInt();
			
			return new Tank(startX, startY, startRot, type, TYPE_AI_BOT, difficulty);
		}
		
		override public function serialize(data:ByteArray):void
		{
			data.writeInt(x);
			data.writeInt(y);
			data.writeInt(rotation);
			data.writeInt(m_indxObj);
			data.writeInt(m_enemyAI.difficulty);
		}
		
		override public function release():void
		{
			removeChild(m_healthBar);
			m_healthBar = null;
			
			m_timerBlinking = null;
			
			if (m_timerBlinking != null)
			{
				m_timerBlinking.stop();
				m_timerBlinking.removeEventListener(TimerEvent.TIMER, updateBlink);
				m_timerBlinking = null;
			}
			
			if (m_enemyAI != null)
			{
				m_enemyAI.release();
				m_enemyAI = null;
			}
			
			if (isGamePlayer())
			{
				m_gamePlayer = null;
			}
			
			super.release();
		}
		
		// Send request to swfManager 
		public static function loadResource(funcHandler:Function):void
		{
			SwfManager.instance.load(m_swfPath, funcHandler);
		}
		
		// Return value if resources is loaded
		public static function isLoaded():Boolean
		{
			return SwfManager.instance.isLoaded(m_swfPath);
		}
		
		public function get playerName():String
		{
			return m_playerName;
		}
		
		public function set playerName(value:String):void
		{
			m_playerName = value;
			
			if (m_healthBar != null)
			{
				(m_healthBar.getChildByName("Name") as TextField).text = m_playerName;
			}
		}
		
		// Move object in direction
		public function moveTo(direction:int):void
		{
			if (isDestroyed)
			{
				return;
			}
			
			//playAll(objectSprite as Sprite);
			objectSprite.play();
			// Set frame according to the direction
			m_currentDirection = direction;
			objectSprite.gotoAndStop(m_currentDirection + 1);
			
			var force:b2Vec2 = new b2Vec2(0.0, 0.0);
			switch(m_currentDirection)
			{
				case DIRECTION_UP:
					force.Add(new b2Vec2(0, -m_currentSpeed));
					//physicalObject.SetLinearVelocity(new b2Vec2(0, physicalObject.GetLinearVelocity().y));
				break;
				
				case DIRECTION_DOWN:
					force.Add(new b2Vec2(0, m_currentSpeed));
					//physicalObject.SetLinearVelocity(new b2Vec2(0, physicalObject.GetLinearVelocity().y));
				break;
				
				case DIRECTION_RIGHT:
					force.Add(new b2Vec2(m_currentSpeed, 0));
					//physicalObject.SetLinearVelocity(new b2Vec2(physicalObject.GetLinearVelocity().x, 0));
				break;
				
				case DIRECTION_LEFT:
					force.Add(new b2Vec2( -m_currentSpeed, 0));
					//physicalObject.SetLinearVelocity(new b2Vec2(physicalObject.GetLinearVelocity().x, 0));
				break;
			}
			
			if (force.x || force.y) 
			{
				//physicalObject.ApplyForce(force, physicalObject.GetWorldCenter());
				physicalObject.SetAwake(true);
				physicalObject.SetLinearVelocity(force);
				
				//if (getTimer() - m_networkUpdate > 100)
				//{
					//m_networkUpdate = getTimer();
					//var msg:MessageCorrectPosition = new MessageCorrectPosition();
					//msg.setData(physicalObject.GetLinearVelocity().x, physicalObject.GetLinearVelocity().y, physicalObject.GetPosition().x, physicalObject.GetPosition().y, m_currentDirection + 1);
					//MessagesHandler.instance.addMessage(msg);
					//OnlineManager.instance.connection.sendMessage(msg);
				//}
			}
		}
		
		// Idle state. Stop all animation
		public function idle():void
		{
			stopAll();
		}
		
		// Retirn current direction
		public function get getDirection():int
		{
			return m_currentDirection;
		}
		
		// Change direction
		public function set setDirection(value:int):void
		{
			m_currentDirection = value - 1;
			objectSprite.gotoAndStop(m_currentDirection + 1);
		}
		
		// Play all nested animation in MovieClip
		public function playAll(animation:Sprite = null):void
		{
			if (m_isAnimationStoped)
			{
				//Utils.playAll(objectSprite as Sprite);
				objectSprite.play();
				m_isAnimationStoped = false;
			}
		}
		
		// Play all nested animation in MovieClip
		public function stopAll():void
		{
			if (!m_isAnimationStoped)
			{
				//Utils.stopAll(objectSprite as Sprite);
				objectSprite.stop();
				m_isAnimationStoped = true;
			}
		}
		
		// Return value if current player is gameplayer
		public function isGamePlayer():Boolean
		{
			if (m_typeGamePlayer == TYPE_GAME_PLAYER)
			{
				return true;
			}
			return false;
		}
		
		public static function getGamePlayer():Tank
		{
			return m_gamePlayer as Tank;
		}
		
		// ========================= ROCKET ==========================
		// Run rocket
		public function doRocket():void
		{
			if ((getTimer() - m_lastTimeRocket > 500))
			{
				m_lastTimeRocket = getTimer();
				
				var dx:int = 0;
				var dy:int = 0;
				var rotation:Number = 0;
				switch(m_currentDirection)
				{
					case DIRECTION_DOWN:
						dy += this.height / 2;
						rotation = 90;
					break;
					
					case DIRECTION_UP:
						dy -= this.height / 2;
						rotation = -90;
					break;
					
					case DIRECTION_LEFT:
						dx -= this.width / 2;
						rotation = 180;
					break;
					
					case DIRECTION_RIGHT:
						dx += this.width / 2;
						rotation = 0;
					break;
				}
				
				new Rocket(this.x + dx, this.y + dy, rotation, this);
				//Main.mainSprite.addChild(m_rocket);
			}
			
			//if (Settings.enableOnline && isGamePlayer())
			//{
				//var msg:MessageDoRocket = new MessageDoRocket();
				//msg.setData(0);
				//MessagesHandler.instance.addMessage(msg);
				//OnlineManager.instance.connection.sendMessage(msg);
			//}
		}
		
		// Update rocket movement 
		override public function update():void
		{
			super.update();
			if (isDestroyed)
			{
				new Explosion(x, y);
				World.instance.objectLayer.removeChild(this);		
				release();
			}
			
			if (m_enemyAI != null)
			{
				m_enemyAI.update();
			}
			
			if (isLoaded())
			{
				addChild(m_healthBar);
			}
			
			//if (isGamePlayer())
			//{
				//if (Settings.enableOnline && getTimer() - m_networkUpdate > 150)
				//{
					//if (physicalObject.IsActive())
					//{
						//m_networkUpdate = getTimer();
						//var msg:MessageCorrectPosition = new MessageCorrectPosition();
						//msg.setData(physicalObject.GetLinearVelocity().x, physicalObject.GetLinearVelocity().y, physicalObject.GetPosition().x, physicalObject.GetPosition().y, m_currentDirection + 1);
						//MessagesHandler.instance.addMessage(msg);
						//OnlineManager.instance.connection.sendMessage(msg);
					//}
				//}
			//}
			
			//if (m_rocket && m_rocket.isExposion)
			//{
				//Main.mainSprite.removeChild(m_rocket);
				//m_rocket = null;
			//}
		}
		
		override public function doDestroy():void
		{			
			m_health -= 5;
			if (m_health <= 0)
			{
				if (m_gamePlayer != this)
				{
					isDestroyed = true;
				}
				m_health = 0;
			}
			
			if (m_healthBar != null)
			{
				(m_healthBar.getChildByName("healthBar") as Sprite).scaleX = m_health / 100;
			}
			
			if (m_timerBlinking == null)
			{
				m_timerBlinking = new Timer(100, 30);
				m_timerBlinking.addEventListener(TimerEvent.TIMER, updateBlink, false, 0, true);
				m_timerBlinking.addEventListener(TimerEvent.TIMER_COMPLETE, cancelBlink, false, 0, true);
				m_timerBlinking.start();
			}
			else
			{
				m_timerBlinking.reset();
				m_timerBlinking.start();
			}
		}
		
		// Destroy effect
		private function updateBlink(e:Event):void
		{
			if (objectSprite != null && objectSprite.filters.length == 0)
			{
				//var filter:GlowFilter = new GlowFilter;  
				//filter.color = 0xFF0000;  

				//filter.blurX = 15;  
				//filter.blurY = 15; 
				//
				//objectSprite.filters = [filter];
				
				var matrix:Array = new Array();
				matrix = matrix.concat([0.93, 0,   0,   0, 0]); // red
				matrix = matrix.concat([0,    0.1, 0,   0, 0]); // green
				matrix = matrix.concat([0,    0,   0.1, 0, 0]); // blue
				matrix = matrix.concat([0,    0,   0,   1, 0]); // alpha

				var filter:ColorMatrixFilter = new ColorMatrixFilter(matrix);  
				
				objectSprite.filters = [filter];
			}
			else if (objectSprite != null)
			{
				objectSprite.filters = [];
			}
		}
		
		private function cancelBlink(e:Event):void
		{
			objectSprite.filters = [];
			
			m_timerBlinking.removeEventListener(TimerEvent.TIMER, updateBlink);
			m_timerBlinking.removeEventListener(TimerEvent.TIMER_COMPLETE, cancelBlink);
			m_timerBlinking = null;
		}
	}
}